<template>
    <div>
        <el-select v-model="selectNames" multiple placeholder="请选择" @remove-tag='removeTag'>
            <el-option style="height: auto" v-for="item in []" :key="item.nodeId">
            </el-option>
            <div slot="empty">
                <el-tree :data="treeJson" ref="tree" nodeKey="nodeId" @check-change="handleCheckChange" show-checkbox
                    check-strictly highlight-current :props="defaultProps" :default-checked-keys="defaultKeys" 
                    :default-expanded-keys="expandedKeys"/>
            </div>
        </el-select>
    </div>
</template>

<script>
    import {
        distributionListData
    } from '@/api/produceController'
    export default {
        data() {
            return {
                checkedData: [],
                treeJson: [],
                flattenJson: [],
                selectNames: [],
                filterDatas: [],
                defaultKeys: [],
                expandedKeys:[],
                userId: '',
                depId: '',
                mapUserId: [],
                mapDepId: [],
                bugIndex: 0,
                defaultProps: {
                    children: "listDown",
                    label: "name",
                },
            }
        },
        props: {
            instructType: {
                type: String,
                default: 'instructType'
            },
            isGetAllLabel: {
                type: Boolean,
                default: true
            },
            editInfo: {
                type: Object,
                default: () => ({})
            }
        },
        methods: {
            getDistributionListData: async function (data) {
                const res = await distributionListData(data)
                if (res.code == 200) {
                    this.treeJson = this.treeDataMap(res.data)
                    this.flattenJson = this.extractTree(this.treeJson, 'listDown')
                    //初始化获取默认勾选选项 defaultKeys
                    if (this.instructType === 'create' && this.isGetAllLabel) { //当树形结构默认有[所有人]时
                        const defaultNodeId = 'user-1'
                        this.defaultKeys.push(defaultNodeId)
                    } else if (this.instructType === 'edit' || this.instructType === 'copy') {
                        let allIdArr = []
                        //一定要添加类型type *** (部门id和人员id可能重复)
                        this.mapUserId.forEach(item => {
                            allIdArr.push({
                                id: item,
                                type: 'user'
                            })
                        })
                        this.mapDepId.forEach(item => {
                            allIdArr.push({
                                id: item,
                                type: 'dep'
                            })
                        })
                        this.handleEcho(allIdArr)
                    }
                }
            },
            //统一获取userId,depId,checkedData
            getTreeInfo() {
                return {
                    userId: this.userId,
                    depId: this.depId,
                    selectNames: this.selectNames
                }
            },
            handleString(payload,isId = false){
                if(payload.length){
                    return !isId ? payload.split(',').map(Number) : payload.split(',')
                }else {
                    return []
                }
            },
            handleDefaultValue(type) {
                if(type === 'create' && this.isGetAllLabel){
                    const defaultId = '-1'
                    this.selectNames.push('所有人')
                    this.userId = defaultId
                    this.mapUserId.push(+defaultId)
                }else if(type === 'edit' || type === 'copy'){
                    const {
                        userId, depId, selectNames
                    } = this.editInfo
                    this.userId = userId
                    this.depId = depId
                    this.mapUserId = this.handleString(userId)
                    this.mapDepId = this.handleString(depId)
                    this.selectNames = this.handleString(selectNames,true)
                }
                this.getDistributionListData({
                    getAllLabel: this.isGetAllLabel
                })
            },
            clearTreeInfo() {
                Object.assign(this.$data, this.$options.data()) //初始化data里面的所有数据
            },
            /**
             * arrs 树形数据
             * childs 树形数据子数据的属性名,常用'children'
             * attrArr 需要提取的公共属性数组(默认是除了childs的全部属性)
             */
            extractTree(arrs, childs, attrArr) {
                let attrList = []
                if (!Array.isArray(arrs) && !arrs.length) return []
                if (typeof childs !== 'string') return []
                if (!Array.isArray(attrArr) || Array.isArray(attrArr) && !attrArr.length) {
                    attrList = Object.keys(arrs[0])
                    //不删除子级listdown *********************
                    // attrList.splice(attrList.indexOf(childs), 1)
                } else {
                    attrList = attrArr
                }
                let list = []
                const getObj = (arr) => {
                    arr.forEach(function (row) {
                        let obj = {}
                        attrList.forEach(item => {
                            obj[item] = row[item]
                        });
                        list.push(obj)
                        if (row[childs]) {
                            getObj(row[childs])
                        }
                    })
                    return list
                }
                return getObj(arrs)
            },
            //将回显的所有id&&type相同的项过滤出来
            handleEcho(allIdArr) {
                let result = []
                result = this.flattenJson.filter(item => {
                    return allIdArr.findIndex(i => item.id === i.id && item.type === i.type) !== -1
                })
                //removeTag 方法会触发 handleCheckChange事件 编辑时需要有默认checkedData值
                this.checkedData = this.unique(result)
                this.defaultKeys = result.map(item => item.nodeId)
                this.expandedKeys = this.defaultKeys
            },
            treeDataMap(data) {
                for (let i = 0; i < data.length; i++) {
                    if (data[i].listDown && data[i].listDown.length) {
                        this.treeDataMap(data[i].listDown)
                    } else if (data[i].nodePid !== 'BaseTreeEntity_null') {
                        data[i].nodeId = data[i].nodePid + data[i].id
                    }
                }
                return data;
            },
            //点击复选框事件
            handleCheckChange(data, checked) {
                if (checked) {
                    // 选中的当前节点的数据
                    this.checkedData.push(data)
                    this.checkedData = this.unique(this.checkedData)
                    this.bugIndex = 0
                    this.checkedEvent(this.treeJson, data.id, data.type)
                } else {
                    let targetIndex = this.checkedData.findIndex(i => i.nodeId === data.nodeId)
                    if (targetIndex >= 0) this.checkedData.splice(targetIndex, 1)
                    this.noCheckedEvent(this.treeJson, data.id, data.type)
                }
                this.selectNames = this.checkedData.map(i => i.name)
            },
            unique(arr) {
                /**
                 * 人员id可能和部门id重复 在去重时 碰到id相同的还需判断一下type是否一样
                 */
                let uniArr = []
                let uniObj = {}
                uniArr = arr.reduce((pre, cur) => {
                    if (uniObj[cur.id]) {
                        if (pre.find(i => i.id === cur.id).type !== cur.type) pre.push(cur)
                    } else {
                        uniObj[cur.id] = true && pre.push(cur)
                    }
                    return pre
                }, [])
                return uniArr
            },
            //勾选事件 (收集userId,depId, 设置勾选状态)
            checkedEvent(arr, id, type) {
                const that = this
                let variable = that[type == 'user' ? 'mapUserId' : 'mapDepId']
                for (let i = 0; i < arr.length; i++) {
                    if (arr[i].listDown && arr[i].listDown.length) {
                        this.checkedEvent(arr[i].listDown, id, type)
                    }
                    if (arr[i].id === id && arr[i].type === type) {
                        /**
                         * bugIndex describe
                         * 当下拉框中含有[所有人]时,点击其它节点时需要将[所有人]选中的状态取消
                         * 节点重复:相同人员可以存在不同部门之间
                         * 当前问题存在:当当下拉框中含有[所有人]时,若其他节点有且只有一个时,节点状态正常显示,当其它节点有重复时,节点需要点击重复的次数才能选中
                         * 当前解决思路:利用下标限制清空tree结构所有节点的勾选状态的次数
                         */
                        if (arr[i].typeFlag === 'all' || this.selectNames.includes('所有人')) {
                            ++this.bugIndex
                            if (this.bugIndex <= 1) this.$refs.tree.setCheckedKeys([])
                        }
                        that.$refs.tree.setChecked(arr[i].nodeId, true, true)
                        /**
                         * 去重
                         * mapUserId,mapDepId中间变量接收userId,depId
                         */
                        if (!variable.includes(arr[i].id)) variable.push(arr[i].id)
                        that[type == 'user' ? 'userId' : 'depId'] = [...variable].toString()
                    }
                }
            },
            //取消勾选 (收集userId,depId, 设置勾选状态)
            noCheckedEvent(arr, id, type) {
                const that = this
                let targetIndex = -1
                let variable = that[type == 'user' ? 'mapUserId' : 'mapDepId']
                for (let i = 0; i < arr.length; i++) {
                    if (arr[i].listDown && arr[i].listDown.length) {
                        this.noCheckedEvent(arr[i].listDown, id, type)
                    }
                    if (arr[i].id === id && arr[i].type === type) {
                        that.$refs.tree.setChecked(arr[i].nodeId, false, true)
                        /**
                         * 取消勾选状态移除相应id
                         * mapUserId,mapDepId中间变量接收userId,depId
                         */
                        targetIndex = variable.findIndex(e => e == arr[i].id)
                        targetIndex >= 0 && variable.splice(targetIndex, 1)
                        that[type == 'user' ? 'userId' : 'depId'] = [...variable].toString()
                    }
                }
            },
            removeTag(tagName) {
                // 人员的名字不可能存在重复，只要账号不同id肯定不同 
                // 人员名字可能和部门名称取重复 -- bug
                // 不考虑人员名字和部门名称可能出现重复的情况  暂定人员名字为唯一标识 通过人员名字去递归找出所有的勾选项然后移除
                this.filterDatas = []
                this.findNodeIdByName(tagName, this.treeJson)
                this.filterDatas.forEach(i => this.$refs.tree.setChecked(i.nodeId, false, true))
            },
            // 通过人员名字去递归找出所有的勾选项然后移除
            findNodeIdByName(tagName, data) {
                const that = this;
                for (let i = 0; i < data.length; i++) {
                    if (data[i].listDown && data[i].listDown.length) {
                        this.findNodeIdByName(tagName, data[i].listDown)
                    }
                    if (data[i].name === tagName) {
                        that.filterDatas.push(data[i])
                    }
                }
                return that.filterDatas
            },
        },
    };
</script>

<style lang="less" scoped>
    ::v-deep .el-tree{
        max-height: 350px;
        overflow-y: auto;
    }
    ::v-deep .el-tag.el-tag--info {
        transition: all 0.1s;
    }
</style>